package cn.bonoon.kernel.web.handlers;

import java.util.List;

import cn.bonoon.handler.impl.StandardAutoManager;
import cn.bonoon.kernel.descriptors.DescriptorFactory;
import cn.bonoon.kernel.descriptors.ObjectDescriptor;
import cn.bonoon.kernel.events.DialogEvent;
import cn.bonoon.kernel.expression.QueryParameter;
import cn.bonoon.kernel.support.entities.Persistable;
import cn.bonoon.kernel.support.services.IService;
import cn.bonoon.kernel.util.StringHelper;
import cn.bonoon.kernel.web.annotations.DialogDefaultButton;
import cn.bonoon.kernel.web.annotations.DialogModelValue;
import cn.bonoon.kernel.web.annotations.WithDialog;
import cn.bonoon.kernel.web.controllers.BaseButtonResolver;
import cn.bonoon.kernel.web.controllers.FormButtonResolver;
import cn.bonoon.kernel.web.html.form.FormBuilder;
import cn.bonoon.kernel.web.models.DialogModel;
import cn.bonoon.kernel.web.resources.DialogResourceRepository;

/**
 * <pre>
 * 需要加载实体数据的处理器
 * 1.根据对象自动生成界面
 * 2.根据服务接口自动加载对象值
 * 3.添加操作按钮
 * </pre>
 * @author jackson
 * 
 * @see AbstractExecuteHandler
 * @see AbstractDialogHandler
 */
public abstract class AbstractDialogFormableHandler<E extends Persistable> extends AbstractDialogHandler{
	protected final IService<E> service;
	protected final Class<?> formClass;
	protected DialogResourceRepository resource;
	private DialogFormInitializer<E> formInitializer;
	
	/**
	 * <pre>
	 * 弹出的编辑对话框，需要往form表单添加一些必要的字段；
	 * 从加载对话框的url->传值->自动生成表单->提交到控制器
	 * 
	 * 这种只是临时的做法，以后有更好的处理方法时应该替换掉
	 * </pre>
	 */
	protected List<QueryParameter> parameters;
//	
//	public void addParameter(String name, String value){
//		if(null == parameters){
//			//一般不会使用路径来传递参数，如果有，也则是1、2个的情况比较多，所以为了节省内存空间，默认情况下认为最多的情况不超过2个参数
//			parameters = new ArrayList<QueryParameter>(2);
//		}
//		parameters.add(new QueryParameter(name, value));
//	}
//	
	private final WithDialog dialogOptions;
	private DialogModelValue[] models;
	@SuppressWarnings("unchecked")
	protected AbstractDialogFormableHandler(HandlerRegister register, IService<E> service, Class<?> formClass) throws Exception {
		super(formClass, register);
		this.service = service;
		this.formClass = formClass;
		dialogOptions = formClass.getAnnotation(WithDialog.class);
		if(null != dialogOptions){
			if(!dialogOptions.initializer().equals(Object.class)){
				try{
					formInitializer = (DialogFormInitializer<E>)dialogOptions.initializer().newInstance();
				}catch(Exception ex){
					ex.printStackTrace();
				}
			}
			models = dialogOptions.models();
		}else{
			models = new DialogModelValue[0];
		}
	}
	
	public AbstractDialogFormableHandler<E> setFormInitializer(DialogFormInitializer<E> formInitializer) {
		this.formInitializer = formInitializer;
		return this;
	}
	/**
	 * <pre>
	 * 默认会根据实体对象的注解进行解析，判断是详细界面、添加或更新的界面
	 * 对对话框的参数设置应该在调用这个方法之前进行
	 * </pre>
	 * @param resolver 打开当前对话框的按钮(也就是打开对话框的url)
	 * @throws Exception 
	 */
	@Override
	public BaseButtonResolver register(BaseButtonResolver resolver)throws Exception {
//		resolver.addParameter(parameters);
		parameters = resolver.getParameters();
		ObjectDescriptor objectDescriptor = DescriptorFactory.objectDescriptor(formClass);
		FormBuilder builder = builder(objectDescriptor, parentRegister.getManager());
//		if(null != parameters){
//			for(QueryParameter ah : parameters){
//				builder.addHidden(ah.getName());
//			}
//		}
		builder.parse();
		
		String onloadedjs = null, beforeSubmit = null;
		if(null != dialogOptions){
			width = dialogOptions.width();
			if(StringHelper.isNotEmpty(dialogOptions.title())){
				title = dialogOptions.title();
			}
			if(dialogOptions.height() > 1){
				height = dialogOptions.height();
			}
			maxHeight = dialogOptions.maxHeight();
			
			closeButton = dialogOptions.closeButton();
			closable = dialogOptions.closable();
			maximizable = dialogOptions.maximizable();
			maximized = dialogOptions.maximized();
			modal = dialogOptions.modal();
			
			onloadedjs = dialogOptions.onloadedjs();
			beforeSubmit = dialogOptions.beforeSubmit();
//		}else{
			
		}
		if(width < 1){
			width = builder.getWidth();//弹出的对话框的边框
			if(height > 1){
				//预计这里将会有滚动条
				width += 24;
			}else{
				width += 14;
			}
		}
		int th = builder.getHeight();
		if(th > height){
			height = th;
		}
		
		resource = new DialogResourceRepository(formClass.getName() + "." + key, builder);
		resource.setOnLoadEvent(builder.getInitBlock());
		
		//在这里添加该对话框的默认按钮，默认是不需要添加按钮
		if(null != defaultButton){
			FormButtonResolver buttonResolver = new FormButtonResolver();
			buttonResolver.setAfterOperate(parentRegister.refreshParentComponenet());
			defaultButton.register(buttonResolver);
			
			StringBuilder initSource = new StringBuilder(builder.getInitSubmit());

			DialogDefaultButton ddb = formClass.getAnnotation(DialogDefaultButton.class);
			if(null != ddb){
				if(!ddb.functionName().isEmpty()){
					buttonResolver.setFunctionName(ddb.functionName());
				}
				if(!ddb.buttonName().isEmpty()){
					buttonResolver.setName(ddb.buttonName());
				}
				initSource.append(ddb.functionBody());
				
				if(!ddb.otherButtonName().isEmpty()){
					FormButtonResolver otherButtonResolver = new FormButtonResolver();
					otherButtonResolver.setAfterOperate(parentRegister.refreshParentComponenet());
					defaultButton.register(otherButtonResolver);
					otherButtonResolver.setName(ddb.otherButtonName());
					StringBuilder otherInitSource = new StringBuilder(builder.getInitSubmit());
					if(!ddb.otherFunctionName().isEmpty()){
						otherButtonResolver.setFunctionName(ddb.otherFunctionName());
					}
					if(!ddb.otherParameterName().isEmpty() && !ddb.otherParameterValue().isEmpty()){
						otherButtonResolver.addParameter(ddb.otherParameterName(), ddb.otherParameterValue());
					}
					otherInitSource.append(ddb.otherFunctionBody());
					otherButtonResolver.setBeforeOperate(otherInitSource.toString());
					addButton(otherButtonResolver);
				}
			}
			if(StringHelper.isNotEmpty(beforeSubmit)){
				initSource.append(beforeSubmit);
			}
			buttonResolver.setBeforeOperate(initSource.toString());
			addButton(buttonResolver);
			//释放内存，通知GC回收，该字段以后不会再用到，除非定义了热重启机制
			//defaultButton = null;
		}
		
//		DialogButtons dbs = formClass.getAnnotation(DialogButtons.class);
//		if(null != dbs){
//			for(DialogButton db : dbs.value()){
//				IFormHandler handler;
//				FormButtonResolver buttonResolver = new FormButtonResolver();
//				if(db.refreshAtFinish()){
//					buttonResolver.setAfterOperate(parentRegister.refreshParentComponenet());
//				}
//				defaultButton.register(buttonResolver);
//				
//			}
//		}
		
		StringBuilder html = new StringBuilder();
		StringBuilder dlgAttrs = new StringBuilder();
		parse(html, resource.getBlock(), dlgAttrs);
		html.append("<div id='$!{di.id}' ").append(dlgAttrs);
		html.append(" $!{di.dialogAttributes}>").append(builder.getHtml()).append("</div>");
		
		resource.getBlock().append(block);
		resource.putStringResource(html);
		
		if(StringHelper.isNotEmpty(onloadedjs)){
			if(resource.getOnLoadEvent() == null){
				resource.setOnLoadEvent(new StringBuilder());
			}
			resource.getOnLoadEvent().append(onloadedjs);
		}
		viewName = resource.getName();
		
		return super.register(resolver);
	}
	/**
	 * 添加该对话框的默认按钮；具体的操作按钮需要根据子类是具体功能来决定，所以应该由子类来指定需要添加的按钮
	 */
	protected AbstractOperateFormHandler<E> defaultButton;
	
	/**
	 * <pre>
	 * 界面的主要内容的创建器，用于生成如form表单内容等
	 * </pre>
	 * @param objectDescriptor
	 * @param initializer
	 * @param setting
	 * @return
	 */
	protected abstract FormBuilder builder(ObjectDescriptor objectDescriptor, StandardAutoManager initializer);
	
	@Override
	protected final void internalExecute(DialogModel model, DialogEvent event) throws Exception {
		initData(model, event);
		model.addBlock(resource.getBlock());
		model.addIncludes(resource.getIncludes());
		model.addScript(resource.getScript());
		model.addLoadEvent(resource.getOnLoadEvent());
		//当前功能所在的路径
		if(null != parameters){
			for(QueryParameter ah : parameters){
				String name = ah.getName();
				model.addObject(name, event.getString(name));
			}
		}
	}
	
	protected void initData(DialogModel model, DialogEvent event) throws Exception{
		Long id = event.getEntityId();
		//可以由url或其它的方式传过来很多的参数
		Object form = null;
		if(null != id && id > 0){
			form = service.get(event, id, formClass);
		}
		if(null != formInitializer){
			form = formInitializer.init(service, model, event, id, form);
		}
		if(null == form && null != dialogOptions && dialogOptions.initFormClass()){
			form = formClass.newInstance();
		}
		model.addForm(form);
		
		for(DialogModelValue mv : models){
			model.addObject(mv.name(), mv.value());
		}
	}
}
